﻿//Everyone

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Management;
using System.Management.Instrumentation;
using System.IO;
using System.Windows.Forms;
using System.Xml;

namespace Tzync
{
    public class Utility
    {
        //Description     : Function to get the CPUID                    
        public static String GetCPUId()
        {
            try
            {
            
            String driveLetter = "";
            SelectQuery query = new SelectQuery( "select name from win32_logicaldisk where drivetype=3");
            ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);
            foreach (ManagementObject mo in searcher.Get())
            {
                driveLetter = mo["name"].ToString().TrimEnd(':');
                break;
            }
            ManagementObject dsk = new ManagementObject(@"win32_logicaldisk.deviceid=""" + driveLetter + @":""");
            dsk.Get();

            string volumeSerial = dsk["VolumeSerialNumber"].ToString();
            return volumeSerial;
            }catch(Exception)
            {
                throw;
            }                               

        }

        public static String GetMotherBoardId()
        {
            String motherBoardID = "";
            ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT Product FROM Win32_BaseBoard");
            // Executing the query...
            // Because the machine has a single Motherborad, then a single object (row) returned.


            ManagementObjectCollection information = searcher.Get();
            foreach (ManagementObject obj in information)
            {
                // Retrieving the properties (columns)    
                // Writing column name then its value    
                foreach (PropertyData data in obj.Properties)
                    motherBoardID = data.Value.ToString();
            }
            // For typical use of disposable objects enclose it in a using statement instead.
            searcher.Dispose();
            return motherBoardID;
        }

        //Description     : Function to calculate the size of a directory
        //Pre-Conditions  : directory is not NULL
        //Post-Conditions : size of the directory is calculated.

        public static long CalculateDirectorySize(DirectoryInfo directory)
        {
            long totalSize = 0;

            // Examine all contained files.
            FileInfo[] files = directory.GetFiles();
            foreach (FileInfo file in files)
            {
                totalSize += file.Length;
            }

            DirectoryInfo[] dirs = directory.GetDirectories();
            foreach (DirectoryInfo dir in dirs)
            {
                totalSize += CalculateDirectorySize(dir);
            }

            return totalSize;
        }

        //Return : int (index)
        //index>=0, if present
        //index<0, if not found
        //Input sorted list of string. StartVal is an optional guess value - default is 0.

        public static int binarySearch(string a, List<String> b, int startVal)
        {

            int listLength = b.Count;
            if (listLength == 0 || startVal > listLength) return -1;

            int lowerBound = 0, upperBound = listLength - 1, moreIndex = -1;
            // Find match in larger folder using binary search

            while (lowerBound <= upperBound)
            {
                if (moreIndex == -1)
                    moreIndex = startVal; // setting initial value proportionally so search space is (hopefully) reduced.
                else
                    moreIndex = (int)(lowerBound + upperBound) / 2; //Binary search updating index.              

                switch (a.CompareTo(b.ElementAt(moreIndex)))
                {
                    case 0: // Filename match!
                        return moreIndex;
                    case 1: //greater
                        lowerBound = moreIndex + 1;
                        break;
                    case -1: //lesser
                        upperBound = moreIndex - 1;
                        break;
                }
            }

            return -1; //No match. It is a difference.                             
        }

        public static int binarySearch(string a, List<String> b)
        {
            return binarySearch(a, b, 0);
        }

        public static string GetMD5Hash(string input)
        {
            System.Security.Cryptography.MD5CryptoServiceProvider x = new System.Security.Cryptography.MD5CryptoServiceProvider();
            byte[] bs = System.Text.Encoding.UTF8.GetBytes(input);
            bs = x.ComputeHash(bs);
            System.Text.StringBuilder s = new System.Text.StringBuilder();
            foreach (byte b in bs)
            {
                s.Append(b.ToString("x2").ToLower());
            }
            string password = s.ToString();
            return password;
        }

        /// <summary>
        /// Hard disk stores file without the slashes and colon so that there will be a unique storing scheme
        /// </summary>
        /// <param name="input">The input to strip</param>
        /// <returns></returns>
        public static String StripString(String input)
        {
            String[] arrWords;
            String concat = "";
            arrWords = input.Split('\\', ':');
            foreach (String str in arrWords)
            {
                concat += str;
            }
            return concat;
        }

        public static String ParseDateTime(DateTime dt)
        {
            DateTime newDateTime = new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, dt.Second);
            //return newDateTime;
            String dateTime = String.Format("{0:dd/MM/yyyy HH:mm:ss}", newDateTime);
            dateTime = dateTime.Replace("/", "-");
            return dateTime;
        }

                /// <summary>
        /// Function to auto resize columns in listview
        /// </summary>
        public static void ResizeColumns(ListView display)
        {
            int contentWidth, headerWidth;
            ColumnHeaderAutoResizeStyle headerResize;

            for (int index = 0; index < display.Columns.Count; index++)
            {
                ColumnHeader header = display.Columns[index];
                header.AutoResize(ColumnHeaderAutoResizeStyle.ColumnContent);
                contentWidth = header.Width;

                header.AutoResize(ColumnHeaderAutoResizeStyle.HeaderSize);
                headerWidth = header.Width;

                if (contentWidth > headerWidth)
                    headerResize = ColumnHeaderAutoResizeStyle.ColumnContent;
                else
                    headerResize = ColumnHeaderAutoResizeStyle.HeaderSize;

                header.AutoResize(headerResize);
            }
        }

        /// <summary>
        /// Checks for new versions of Tzync by reading XML file on server
        /// </summary>
        public static String CheckForUpdate()
        {
            // in newVersion variable we will store the
            // version info from xml file
            Version newVersion = null;
            // and in this variable we will put the url we
            // would like to open so that the user can
            // download the new version
            // it can be a homepage or a direct
            // link to zip/exe file
            string url = "";
            XmlTextReader reader = null;
            try
            {
                // provide the XmlTextReader with the URL of
                // our xml document
                string xmlURL = "https://tzync.googlecode.com/svn/trunk/resources/app_version";
                reader = new XmlTextReader(xmlURL);
                // simply (and easily) skip the junk at the beginning
                reader.MoveToContent();
                // internal - as the XmlTextReader moves only
                // forward, we save current xml element name
                // in elementName variable. When we parse a
                // text node, we refer to elementName to check
                // what was the node name
                string elementName = "";
                // we check if the xml starts with a proper
                // "ourfancyapp" element node
                if ((reader.NodeType == XmlNodeType.Element) &&
                    (reader.Name == "Tzync"))
                {
                    while (reader.Read())
                    {
                        // when we find an element node,
                        // we remember its name
                        if (reader.NodeType == XmlNodeType.Element)
                            elementName = reader.Name;
                        else
                        {
                            // for text nodes...
                            if ((reader.NodeType == XmlNodeType.Text) &&
                                (reader.HasValue))
                            {
                                // we check what the name of the node was
                                switch (elementName)
                                {
                                    case "version":
                                        // thats why we keep the version info
                                        // in xxx.xxx.xxx.xxx format
                                        // the Version class does the
                                        // parsing for us
                                        newVersion = new Version(reader.Value);
                                        break;
                                    case "url":
                                        url = reader.Value;
                                        break;
                                }
                            }
                        }
                    }
                }

                // get the running version
                Version curVersion = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
                // compare the versions
                if (curVersion.CompareTo(newVersion) < 0)
                    return url;
                else
                    return "";
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                if (reader != null) reader.Close();
            }

        }
        /// <summary>
        /// Does a binary search with an optional guess value.
        /// </summary>
        /// <param name="a">String to search for</param>
        /// <param name="b">List of strings to search in </param>
        /// <param name="startVal">Optional guess value</param>
        /// <returns>Position if found. -1 if not found.</returns>
        public static int BinarySearch(string a, List<String> b, int startVal)
        {

            int listLength = b.Count;

            if (listLength == 0 || startVal > listLength) return -1;

            int lowerBound = 0, upperBound = listLength - 1, moreIndex = -1;
            // Find match in larger folder using binary search

            while (lowerBound <= upperBound)
            {
                if (moreIndex == -1)
                    moreIndex = startVal; // setting initial value proportionally so search space is (hopefully) reduced.
                else
                    moreIndex = (int)(lowerBound + upperBound) / 2; //Binary search updating index.              

                switch (CompareFileNames(a, b.ElementAt(moreIndex)))
                {
                    case 0: // Filename match!
                        return moreIndex;
                    case 1: //greater
                        lowerBound = moreIndex + 1;
                        break;
                    case -1: //lesser
                        upperBound = moreIndex - 1;
                        break;
                }
            }

            return -1; //No match. It is a difference.                             
        }
        /// <summary>
        /// Compare 2 file names in windows file storage order
        /// </summary>
        /// <param name="a">First string</param>
        /// <param name="b">Second string</param>
        /// <returns>-1, 0 or 1 depending on greater, lesser or equal</returns>
        public static int CompareFileNames(String a, String b)
        {
            int apos, bpos;
            apos = FindSpecialChars(a);
            bpos = FindSpecialChars(b);
            if (apos > 0 || bpos > 0)
            {
                apos = (apos == -1) ? bpos : apos;
                bpos = (bpos == -1) ? apos : bpos;

                int prev = a.Substring(0, apos).CompareTo(b.Substring(0, bpos));
                if (prev == 0)
                {
                    int curr = -1 * a.Substring(apos, 1).CompareTo(b.Substring(bpos, 1));
                    if (curr == 0)
                    {
                        return CompareFileNames(a.Substring(apos), b.Substring(bpos));
                    }
                    return curr;
                }
                return prev;


            }
            else return a.CompareTo(b);
        }
        /// <summary>
        /// REturns the first occurence of a non-alphabet character in String x.
        /// </summary>
        /// <param name="x"></param>
        /// <returns></returns>
        public static int FindSpecialChars(String x)
        {
            for (int i = 0; i < x.Length; i++) if (!Char.IsLetter(x, i)) return i;
            return -1;
        }
        public static int BinarySearch(string a, List<String> b)
        {
            return BinarySearch(a, b, 0);
        }
    }
}
